{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## FFT TESTBENCH\n",
    "\n",
    "This notebook takes two inputs (real and imaginary) and gived the real and imaginary parts of the FFT outputs using AXI4. It is then compared with software version of FFT"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/javascript": [
       "\n",
       "require(['notebook/js/codecell'], function(codecell) {\n",
       "  codecell.CodeCell.options_default.highlight_modes[\n",
       "      'magic_text/x-csrc'] = {'reg':[/^%%microblaze/]};\n",
       "  Jupyter.notebook.events.one('kernel_ready.Kernel', function(){\n",
       "      Jupyter.notebook.get_cells().map(function(cell){\n",
       "          if (cell.cell_type == 'code'){ cell.auto_highlight(); } }) ;\n",
       "  });\n",
       "});\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from pynq import Overlay\n",
    "import numpy as np\n",
    "from pynq import Xlnk\n",
    "from pynq.lib import dma\n",
    "from scipy.linalg import dft\n",
    "import matplotlib.pyplot as plt\n",
    "import time"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "ol=Overlay('fft.bit')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "NUM_SAMPLES = 1024\n",
    "\n",
    "real_error=np.zeros(NUM_SAMPLES)\n",
    "imag_error=np.zeros(NUM_SAMPLES)\n",
    "ind=np.arange(NUM_SAMPLES)\n",
    "real_rmse=np.zeros(NUM_SAMPLES)\n",
    "imag_rmse=np.zeros(NUM_SAMPLES)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "xlnk = Xlnk()\n",
    "in_r = xlnk.cma_array(shape=(NUM_SAMPLES,), dtype=np.float32) \n",
    "in_i = xlnk.cma_array(shape=(NUM_SAMPLES,), dtype=np.float32)           \n",
    "out_r = xlnk.cma_array(shape=(NUM_SAMPLES,), dtype=np.float32) \n",
    "out_i = xlnk.cma_array(shape=(NUM_SAMPLES,), dtype=np.float32)\n",
    "a = [i for i in range(NUM_SAMPLES)]\n",
    "a=np.cos(a)\n",
    "real=a.real                # Change input real and imaginary value here\n",
    "img=a.imag\n",
    "np.copyto(in_r, real)\n",
    "np.copyto(in_i, img)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "ename": "AttributeError",
     "evalue": "Could not find IP or hierarchy hls_fft_float_0 in overlay",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mAttributeError\u001b[0m                            Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-5-9dc9e45e5a63>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mfft_ip\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mol\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mhls_fft_float_0\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      3\u001b[0m \u001b[0mfft_ip\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mwrite\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m0x10\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0min_r\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mphysical_address\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      4\u001b[0m \u001b[0mfft_ip\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mwrite\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m0x18\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0min_i\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mphysical_address\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      5\u001b[0m \u001b[0mfft_ip\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mwrite\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m0x20\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mout_r\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mphysical_address\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/pynq/overlay.py\u001b[0m in \u001b[0;36m__getattr__\u001b[0;34m(self, key)\u001b[0m\n\u001b[1;32m    335\u001b[0m         \"\"\"\n\u001b[1;32m    336\u001b[0m         \u001b[0;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mis_loaded\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 337\u001b[0;31m             \u001b[0;32mreturn\u001b[0m \u001b[0mgetattr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_ip_map\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mkey\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    338\u001b[0m         \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    339\u001b[0m             \u001b[0;32mraise\u001b[0m \u001b[0mRuntimeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Overlay not currently loaded\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/pynq/overlay.py\u001b[0m in \u001b[0;36m__getattr__\u001b[0;34m(self, key)\u001b[0m\n\u001b[1;32m    756\u001b[0m         \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    757\u001b[0m             raise AttributeError(\n\u001b[0;32m--> 758\u001b[0;31m                 \"Could not find IP or hierarchy {} in overlay\".format(key))\n\u001b[0m\u001b[1;32m    759\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    760\u001b[0m     \u001b[0;32mdef\u001b[0m \u001b[0m_keys\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mAttributeError\u001b[0m: Could not find IP or hierarchy hls_fft_float_0 in overlay"
     ]
    }
   ],
   "source": [
    "\n",
    "fft_ip = ol.fft_0\n",
    "fft_ip.write(0x10,in_r.physical_address)\n",
    "fft_ip.write(0x18,in_i.physical_address)\n",
    "fft_ip.write(0x20,out_r.physical_address)\n",
    "fft_ip.write(0x28,out_i.physical_address)\n",
    "v=time.time()\n",
    "fft_ip.write(0x00,1)\n",
    "print(time.time()-v)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Verifying Functionality "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.0037813186645507812\n"
     ]
    }
   ],
   "source": [
    "c=time.time()\n",
    "golden_op=np.fft.fft(a)\n",
    "print(time.time()-c)\n",
    "for i in range(NUM_SAMPLES):\n",
    "\n",
    "    real_error[i]=\"{0:.6f}\".format(abs(out_r[i]-golden_op.real[i]))\n",
    "    imag_error[i]=\"{0:.6f}\".format(abs(out_i[i]-golden_op.imag[i]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Real Part RMSE:  2.04459558196e-05 Imaginary Part RMSE: 1.80089224848e-05\n",
      "PASS\n"
     ]
    }
   ],
   "source": [
    "sum_sq_real=0\n",
    "sum_sq_imag=0\n",
    "for i in range(NUM_SAMPLES):\n",
    "    sum_sq_real =sum_sq_real+(real_error[i]*real_error[i])\n",
    "    real_rmse = np.sqrt(sum_sq_real / (i+1))\n",
    "    sum_sq_imag =sum_sq_imag+(imag_error[i]*imag_error[i])\n",
    "    imag_rmse = np.sqrt(sum_sq_imag / (i+1))\n",
    "print(\"Real Part RMSE: \", real_rmse, \"Imaginary Part RMSE:\", imag_rmse)    \n",
    "if real_rmse<0.001 and imag_rmse<0.001:\n",
    "    print(\"PASS\")\n",
    "else:\n",
    "    print(\"FAIL\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Displaying Error and Output"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0xac99e230>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.figure(figsize=(10, 5))\n",
    "plt.subplot(1,2,1)\n",
    "plt.bar(ind,real_error)\n",
    "plt.title(\"Real Part Error\")\n",
    "plt.xlabel(\"Index\")\n",
    "plt.ylabel(\"Error\")\n",
    "#plt.xticks(ind)\n",
    "plt.tight_layout()\n",
    "\n",
    "plt.subplot(1,2,2)\n",
    "plt.bar(ind,imag_error)\n",
    "plt.title(\"Imaginary Part Error\")\n",
    "plt.xlabel(\"Index\")\n",
    "plt.ylabel(\"Error\")\n",
    "#plt.xticks(ind)\n",
    "plt.tight_layout()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAfAAAAEYCAYAAACju6QJAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMS4xLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvAOZPmwAAIABJREFUeJzt3Xm4HGWZ9/HvLwscICEBEiEkQAIGlYhCTNhVZFNQCC4EEVkUxBmW12VmFJcXAvKOgoKCjjgISmBQQRSFDMhmArITkH1LgAAJgYQAWSAh2/3+0XVC53CW6j5dXV3dv8919XVq6+q7zzl330/V83SVIgIzMzMrlj55B2BmZmaVcwE3MzMrIBdwMzOzAnIBNzMzKyAXcDMzswJyATczMysgF3AzM7MCcgFvMpJOlDRd0luSLu6wbm9JT0h6U9JUSVuVrfuJpBmSFifbHNnF/o+UFJKO7SaGPSWtlrQkecyWdIWk8R22C0lvlG33uqTDy+aXdtjPkl7+eswy0V3eJevzyr0lkq5J1k2StKLDum9JerRsfpWkZWXz303x3kcmcV3bYfn/SJrU0/Otei7gzedF4AzgN+ULJQ0B/gz8X2BjYDpwedkmbwAHAoOAo4BzJe3WYR8bAd8FHk0TR0QMAAYCuwBPAP+QtHeH7T4YEQOSx+CIuKx9Hti/fT9ly8waUad5B/nlXtnjwLJ1l3dYd1ZEjCnLr38AJ5at/8+0vwBg545xW7ZcwJtMRPw5Iv4CLOiw6jPAoxHxx4hYBkwCPijpvcnzTo2IJyJidUTcTSmRd+2wjx8C5wGvVBBPRMTsiDgFuBA4s6o3ZtbAusk7yCn3cnAW8P86WyHpaEm3dVgWkt6dTF8s6ZeSrkuO/G+XtJmkn0l6LTkzsWPZc2dJ+o6kx5L1v5XUlqx7RNKBZdv2l/RK+fObhQt46xgDPNg+ExFvAE8ny9ciaT1gPGWtfUk7AeOAX/Uihj8DYyVt0It9mBVNI+RePfwS2FbSPlU+fyLwfWAI8BZwJ3B/Mn8lcE6H7Q8HPg5sA2ybPBfgEuCLZdsdAMyNiH9WGVfDcgFvHQOAhR2WLaR0irujX1H6wLkeQFJfSsl5YkSs7kUMLwICBpctuz/p+35d0nm92LdZo6p37m1ellOvS5pYtm5ih3WbV/ZWurWU0hH4GVU+/6qIuC85S3EVsCwiLomIVZS6HDoeQf8iIl6IiFeT1z0sWf4/wAGSNkzmjwAurTKmhtYv7wCsbpYAG3ZYtiGwuHyBpB8D7wc+Fm/f6eZ44KGIuKvjTiVtCTzWPt9DP/VwIIDXy5aNjYiZad+EWQHVO/dejIgRXcRyRUR8sYt1qXQYTLpdh9UXAv9Rfgq7Ai+XTS/tZL7jZ8sLZdPPAZsDRMSLkm4HPivpKkpjab5WRTwNzwW8dTxKaYAMAMlp7G1Y+1TdaZT+2T8aEYvKnrs38FFJByTzGwM7StohIk7knYnVlU8D9yenEM1aRSPkXs10bKRLGlm2bnnyXn7A2gPu3gDWL3vOZjUIZYuy6S0pneFrNxk4llKNuzMi5tTg9RqOT6E3GUn9ksEcfYG+ktok9aN0Sur9kj6brD+FUsv+ieR53wG+AOwTER0H4hwNvA/YIXlMB04DvpciHkkaLulUSgnV49dSzIqmm7yDnHIvR5cCbcAnypY9CIyRtEPyO5hUg9c5QdIISRtT+n2Uj+z/CzCW0pH3JTV4rYbkAt58vk/pdNPJlAZyLAW+HxHzgc9S6it6DdgZ+HzZ8/6TUit2ZsfvgEbE6xHxUvsDWA4sioiO/XrlNk9OtS0B7gW2B/aMiBtq+WbNGkSneQeQQ+7lKumzPoXS2YL2ZU8BpwM3ATOA2zp/dkV+B9wAPENpUOCavveIWAr8CRhFafBsU9LbXS1mZmaNT9Is4NiIuKmbbU4Btu1tn38jcx+4mZk1leS0+jGURqA3LZ9CNzOzpiHpK5RGqF8XEbfmHU+WfArdzMysgHwEbmZmVkCF7gMfMmRIjBw5Mu8wzHJz3333vRIRQ/OOo9ac29bK0uZ1oQv4yJEjmT59et5hmOVG0nN5x5AF57a1srR57VPoZmZmBeQCbmZmVkAu4GZmZgVU6D5wa10rVqxg9uzZLFu2LO9Q6qKtrY0RI0bQv3//vEMxy4zzujIu4FZIs2fPZuDAgYwcORJJeYeTqYhgwYIFzJ49m1GjRuUdjllmnNeV8Sl0K6Rly5axySabNH2SA0hik002aZmjEmtdzuvKuIBbYbVCkrdrpfdqra2V/td7+15dwJtERHDH06/QrJfGXbRsBY/Madg7KJpl5uVFy5g5b0neYWTmyZcW88qSt/IOo5BcwJvEn+6fwxd+fTd/vn9O3qFk4siL7uFTP6/FLYQbw9FHH82VV16ZdxhWADv/583sc84teYeRmY//7Fb2Prt53l89czvTAi5plqSHJT0gaXqybGNJN0qakfzcKFkuSedJminpIUljs4yt2Tz/6psAvPDamzlHko0HXng97xC6FBGsXr067zDqyrlttbRw6Yq8Q+hUo+d2PY7APxYRO0TEuGT+ZODmiBgN3JzMA+wPjE4exwHn1yE2s6rMmjWL973vfRx//PGMHTuWSy+9lF133ZWxY8dyyCGHsGRJ6ZTn6aefzvjx43n/+9/Pcccd12xdHM5tazpFyu08vkY2AdgzmZ4MTAO+nSy/JEq/hbskDZY0LCLm5hCjFchp1zzKYy8uquk+t9t8Q049cEy32zz55JP89re/5fTTT+czn/kMN910ExtssAFnnnkm55xzDqeccgonnngip5xyCgBHHHEEU6ZM4cADD6xprA3EuW01k1deQ3FyO+sCHsANkgL474i4ANi0LHFfAjZNpodTugl7u9nJsrWSXNJxlFrxbLnllhmGbta9rbbail122YUpU6bw2GOPsfvuuwOwfPlydt11VwCmTp3KWWedxZtvvsmrr77KmDFjmqWAO7etaRUlt7Mu4HtExBxJ7wJulPRE+cqIiOQDILXkg+ICgHHjxjXV+UirTpoWdRY22GADoNRPtu+++/L73/9+rfXLli3j+OOPZ/r06WyxxRZMmjSpmb7L7dy2TOWV11Cc3M60Dzwi5iQ/5wFXATsBL0saBpD8nJdsPgfYouzpI5JlZg1tl1124fbbb2fmzJkAvPHGGzz11FNrEnrIkCEsWbKkqUadO7etFTR6bmdWwCVtIGlg+zSwH/AIcDVwVLLZUcBfk+mrgSOTEau7AAvdR2ZFMHToUC6++GIOO+wwPvCBD7DrrrvyxBNPMHjwYL7yla+w/fbbc/DBBzN+/Pi8Q60J57a1ikbP7SxPoW8KXJVcaaYf8LuI+Juke4ErJB0DPAdMTLa/FjgAmAm8CXwpw9isoCKiIa7UNHLkSB555JE183vttRf33nvvO7Y744wzOOOMM96x/OKLL84yvKw5t61pFSm3MyvgEfEM8MFOli8A9u5keQAnZBWPmdWGc9usMfhKbGZmZgXkAm5mZlZALuDNormu8NWlFnmbZmY9cgE3MzMrIBfwZtEAI7PNzKx+XMDNqrDbbrvlHYKZZaBIue0C3ixapHO4Ud7lHXfckXcIZpaBIuW2C7hZFQYMGADAtGnT+OhHP8rEiRPZdtttOfnkk7nsssvYaaed2H777Xn66acBuOaaa9h5553Zcccd2WeffXj55ZcBmD9/Pvvuuy9jx47lq1/9KltttRWvvPJKbu/LrNUVKbfzuJ2oZaGV+8CvOxleeri2+9xse9j/R6k2ffDBB3n88cfZeOON2XrrrTn22GO55557OPfcc/n5z3/Oz372M/bYYw/uuusuJHHhhRdy1llncfbZZ3Paaaex11578Z3vfIe//e1vXHDBBbV9H2ZFlXNeQ+Pntgu4WS+NHz+eYcOGAbDNNtuw3377AbD99tszdepUAGbPns2hhx7K3LlzWb58OaNGjQLgtttu46qrrgLgE5/4BBtttFEO78DMOtPoue0C3ixapQ88AuhwtqGCFnUW1l133TXTffr0WTPfp08fVq5cCcBJJ53EN7/5TQ466CCmTZvGpEmT8gjVrDhyzmto/Nx2H7hZHSxcuJDhw4cDMHny5DXLd999d6644goAbrjhBl577bVc4jOz6uSZ2y7gzaKV+8ALYNKkSRxyyCF8+MMfZsiQIWuWn3rqqdxwww2MHTuW6667jmHDhjFw4MAcIzWzSuSZ2z6FblaFJUuWALDnnnuy5557rlk+bdq0NdPl6yZMmMCECRPesZ9BgwZx/fXX069fP+68806mTp261mk7M6uvIuW2C3izaJU+8LwDqLHnn3+eiRMnsnr1atZZZx1+/etf5x2SmdVAPXLbBbzJqOMAL2too0eP5p///GfeYZhZjdUjt90H3mSi6Y5RuxYtctYBWuu9Wmtrpf/13r5XF/Bm0WKD2Nra2liwYEFLJHtEsGDBAtra2vIOxSxTzuvK+BS6FdKIESOYPXs28+fPzzuUumhra2PEiBF5h2GWKed1ZVzAm0ULtFjh7bfZv3//NVc8MrPm4LyuTOoCLuldwJpj/Yh4PpOIzMzMrEc9FnBJBwFnA5sD84CtgMeBMdmGZhVpsT5wqx03zs2KKc0gth8AuwBPRcQoYG/g9kyjMrPMSTpI0gzgWeAWYBZwXa5BmVlqaQr4iohYAPSR1CcipgI7ZByXVapV+sBb6GtydeDGuVmBpekDf13SAOBW4DJJ84CV2YZlZnWwIiIWSFrTOJd0Zt5BmVk6aQr4BGAp8A3gcGAQcFqWQVkV3AdulXPj3KzA0pxCPyUiVkfEyoiYHBHnAd/OOjAzy9wE4E1KjfO/AU8Dn8o1IjNLLU0B37eTZfunfQFJfSX9U9KUZH6UpLslzZR0uaR1kuXrJvMzk/Uj076G0Tp94K3xNuul6sa589osf10WcEn/Kulh4D2SHip7PAs8VMFrfI3S187anQn8NCLeDbwGHJMsPwZ4LVn+02Q7q5BvZmIV6E3j3HltlrPujsB/BxwIXJ38bH98KCK+mGbnkkYAnwQuTOYF7AVcmWwyGTg4mZ6QzJOs3zvZ3irgUdrWk942zp3XZo2hy0FsEbEQWAgcBmtd7GGApAEpL/bwM+BbwMBkfhPg9YhoHygzGxieTA8HXkhee6Wkhcn2r5TvUNJxwHEAW265ZYoQWoQ/Ey2931H6vvcPgZPLli+OiFdTPL/meQ3ObbNK9dgHLunAai72IOlTwLyIuK+3QZaLiAsiYlxEjBs6dGgtd11s7hy2lCJiYUTMiojDIuI5St8yCUqN824rZ1Z5ncTl3DarQJpBbGdQ3cUedgcOkjQL+AOlU2znAoMltR/5jwDmJNNzgC0AkvWDgAXp3oa1cx+4pVVl49x5bdYgMrsSW0R8JyJGRMRI4PPA3yPicGAq8Llks6OAvybTVyfzJOv/Hq1wU9gacx+4VaDixrnz2qxxpCngHS/2cC69u9jDt4FvSppJqS/somT5RcAmyfJvsnbfnPXEfeBWuVpeJtl5bVZnaa/Etoy1r8R2eiUvEhHTgGnJ9DPATp1ssww4pJL9WpkWOahpkbdZL726Epvz2ixfPRbwiHijbHZylxtaQ3AfuFWg141zM8tPlwVc0mLoukM1IjbMJCLrFfeBW1punJsVW3ffAx8IIOl04CXgUkCUWuoDu3qe5cR94JaSG+dmzSFNH/jHI2LnsvnzJd0NnJVRTFaNFukc9hmG3nPj3Kw5pBmFvkrS4cnNC/pIOhxYlXVgVh33gVsFPh4Rv4yIxRGxKCLOBz6bd1Bmlk6aAv4FYCLwcvI4JFlmZsXmxrlZgaUZhT6L0mhVKwCfYrYKfIHSVdTOpdQnfjtunJsVRpo+cLOG0SJd/XXhxrlZsaU5hW4F4j5wM7PWkOZuZH3rEYiZmZmll+YIfIakH0vaLvNorNfcB25puXFuVmxpCvgHgaeACyXdJek4Sb7Qg+XCzZOacuPcrMB6LODJd0R/HRG7Ubrj0KnAXEmTJb078witIu4Dtwq4cW5WYKn6wCUdJOkq4GfA2cDWwDXAtRnHZ2YZcePcrNjSfI1sBjAV+HFE3FG2/EpJH8kmLKuW+8AtraQP/JPAl4CRlBrnlwEfptQ43za34MysR90W8CTBL46ITm8xGBH/J5OozLoQ/iJ4LblxblZg3Z5Cj4hVwMfqFIvVgPvALY2yxvkxHYo34Ma5WRGkGYV+h6RfSPqwpLHtj8wjM7PMuHFuVnxp+sB3S36Wn0YPYK/ah2O95T5wq8Adkn4BXA680b4wIu7PLyQzSyvNzUzcSreG4eZJTblxblZgqW5mIumTwBigrX1ZVwPbLF/uA7e03Dg3K7YeC7ikXwHrU+ovuxD4HHBPxnGZWR24cW5WXGkGse0WEUcCr0XEacCuwBbZhmVmWUsa54cCJwECDgG2yjUoM0stTQFfmvx8U9LmwApgVHYhmXXNXwOvKTfOzQosTR/4FEmDgR8D91Ma5HJhplGZWT10bJwvwI1zs8JIMwr9B8nknyRNAdoiYmG2YZlZHbhxblZgaUeh70bpWsn9knki4pIM4zKzjLlxblZsaUahXwpsAzwArEoWB9BtAZfUBtwKrJu8zpURcaqkUcAfgE2A+4AjImK5pHWTfX6I0qm8QyNiVjVvqpX5Qi5WiWoa585ts8aQ5gh8HLBdVH4XibeAvSJiiaT+wG2SrgO+Cfw0Iv6QjII9Bjg/+flaRLxb0ueBMymNkDV7m9snNVNt4xzntllDSDMK/RFgs0p3HCVLktn+yaP9Kk9XJssnAwcn0xOSeZL1e0vyVUkq5Au5WAXGAbtHxPERcVLy6PEmJs5ts8aQpoAPAR6TdL2kq9sfaXYuqa+kB4B5wI3A08DrEbEy2WQ2MDyZHg68AJCsX0jpVFzHfR4nabqk6fPnz08Thpl1rqrGOTi3zRpBmlPok6rdeXLHox2Ska5XAe+tdl9l+7wAuABg3LhxPqHagfvArQLtjfN7KJ0WByAiDurpic5ts/yl+RrZLb19kYh4XdJUSheKGCypX9ISHwHMSTabQ+kiErMl9QMGURrwYraGGyg1Nam3O3Bum+Wny1Pokm5Lfi6WtKjssVjSop52LGlo0jpH0nrAvsDjwFRK11MHOAr4azJ9dTJPsv7vVQyca3nuA7e0IuKWzh49Pc+5bdYYujwCj4g9kp8Dq9z3MGCypL6UGgpXRMQUSY8Bf5B0BvBP4KJk+4uASyXNBF4FPl/l65pZNyTdFhF7SFrM2uP6RWmM2oY97MK5bdYA0nwPfONOFi+OiBXdPS8iHgJ27GT5M8BOnSxfRulmCmaWod42zp3bZo0hzSC2+yn1X71GqYU+GJgraR7wlYi4L8P4zNbiE6+1U23j3MwaQ5qvkf0NOCAihkTEJsD+wBXA8cAvswzOzDJ1PzAfeAqYkUw/K+l+SR/KNTIz61GaAj4uIq5vn4mIG4CPRMRdlC6laGbF5Ma5WYGlKeCvSvq2pK2Sx7eA15IBLKszjs/MsuPGuVmBpSngX6D0nc6/JI8tk2V9gYnZhWb2Tu4Cryk3zs0KLM2FXF4BTupi9czahmNmdfQF4FRKDXOA23Hj3Kww0nyNbCjwLWAM0Na+PCL2yjAuM8uYG+dmxZbma2SXAZcDnwL+hdIVlXynAbOCc+PcrNjS9IFvEhEXASuSSy1+Gdgl47jMOuUrcNbUZcATwCjgNGAWcG+eAZlZemkKePtFHeZK+qSkHSkNajOzYnPj3KzA0pxCP0PSIODfgJ8DGwLfyDQqM6uHtRrnwIu4cW5WGGlGoU9JJhcCH8s2HDOrIzfOzQoszSj0UZRGqo4s3z4iDsouLKtUq/QMt8r7rAc3zs2KLc0p9L9Quh3gNfjiDmZNw41zs2JLU8CXRcR5mUdivaK8A7AicuPcrMDSFPBzJZ0K3AC81b4wIu7PLCozqwc3zs0KLE0B3x44AtiLt1vpkcxbg2iVvmF/Dbym3Dg3K7A0BfzTwNYRsTzrYMysrtw4NyuwNAX8QWAwMC/jWKwX3AduVXDj3KzA0hTwTYEnJN3L2qfZPFLVrNjcODcrsDQF/NTMo7Bea5Wu4WiZd1oXbpybFViaK7HdUo9AzKzu3Dg3K7AuC7ik2yJiD0mLWfsAT0BExIaZR2epuQ/cKuXGuVmxdVnAI2KP5OfA+oVjZllz49ysOaTpA7cCaJme4ZZ5o9lx49ysOaS5H7gViHwu3cysJbiANxlfqczMiiL8gdUrmRVwSVtImirpMUmPSvpasnxjSTdKmpH83ChZLknnSZop6SFJY7OKrRn5wNvqxblt1hi6LOCSFkta1NUjxb5XAv8WEdsBuwAnSNoOOBm4OSJGAzcn8wD7A6OTx3HA+b14Xy2nVdqxrfI+G5xz26wBdDcKfSCApNOBl4BLKR3oHQ70OPglIuYCc5PpxZIeB4YDE4A9k80mA9OAbyfLL4nSOZW7JA2WNCzZj6XkPnDrSSejz9fS0yh057ZZY0gzCv3jEbFz2fz5ku4Gzkr7IpJGAjsCdwObliXuS5SuBgWlD4AXyp42O1nmJK+Au5SsJ71tnJdzbltv+POqd9L0ga+SdLikvpL6SDocWJX2BSQNAP4EfD0i1jr1nrTIK/oTSjpO0nRJ0+fPn1/JU5uaD7ytCh+PiF9GxOKIWBQR5wOfTftk57ZZvtIU8C8AE4GXk8chybIeSepPKcEvi4g/J4tfljQsWT+Mt2+kMAfYouzpI5Jla4mICyJiXESMGzp0aJowzKxzVTfOndtm+euxgEfErIiYEBFDImJoRBwcEbN6ep4kARcBj0fEOWWrrgaOSqaPAv5atvzIZMTqLsBC95Gl1ypnonzKraaqapw7t80aQ4994JKGAl8BRpZvHxFf7uGpuwNHAA9LeiBZ9l3gR8AVko4BnqP0AQJwLXAAMBN4E/hS6ndhZhVLGuITqniqc9tqwu3x3kkziO2vwD+Am6ig7zsibqPrrtm9O9k+gBPS7t/W5j5wq1S1jXPntlljSFPA14+Ib2ceiZnVW1WNczNrDGkK+BRJB0TEtZlHY1VrlVNR0TLvtC7cODcrsDSj0L9GqYgvTa7CtjjlldjMrLFNkXRA3kFY6/K10HunxyNw33KwGNwHblX4GvBdSW8BK/D9wM0KJdX9wJObEowG2tqXRcStWQVlZtlz49ys2NJ8jexYSi31EcADlG5ecCewV7ahWSVa5USUz7jVlhvnZsWVtg98PPBcRHyM0nWPfZ3DBuWbmVhaSeP8VuB64LTk56Q8YzKz9NIU8GURsQxA0roR8QTwnmzDsmr5CNUq4Ma55cofV72Tpg98tqTBwF+AGyW9BryYbVhWKR94WxWWRcQySWsa55LcODcriDSj0D+dTE6SNBUYBPwt06isYq3Skm2V91knbpybFViqUejtIuKWrAKx2nAfuKXlxrlZsVVUwK3xuQ/cquHGueXBn1e9k2YQmxWAD7zNzFqLC3iTaJWGrC+9aGZW0uUpdEmL6bwu+HKLDcx94GZmraHLAu7LLBaTD1CtJ26cW6Pw3QV7J/UgNknvYu3LLT6fSURWFR94W1punJs1hzTXQj8IOBvYHJgHbAU8DozJNjSrRKu0Y32GofbcODcrpjSD2H5A6QYmT0XEKGBv4PZMo7KquQ/c0pJ0kKQZwLPALcAs4LpcgzKz1NIU8BURsQDoI6lPREwFdsg4LjPLnhvnZgWWpg/8dUkDgH8Al0maB6zMNiyrlk8xWwVWRMQCSWsa55LOzDsoax3+vOqdNAV8ArAU+DpwOKXLLZ6eZVBmVhdunJsVWJqbmbwhaStgdERMlrQ+0Df70Kwa7gO3CrhxblZgaUahfwU4DtgY2AYYDvyKUn+ZmRWUG+dmxZZmENsJwO7AIoCImAG8K8ugrHruU7K0ksb5lcB/J4uGU7q1qJkVQJoC/lZELG+fkdSP1vnasTUYN1Bqyo1zswJLU8BvkfRdYD1J+wJ/BK7JNiyrlvvArQJunJsVWJoCfjIwH3gY+CpwLfD9LIMys7pw49yswLot4JL6ApdExK8j4pCI+Fwy3WMrXdJvJM2T9EjZso0l3ShpRvJzo2S5JJ0naaakhySN7fU7a1E+xWwVqKpx7ty2WvHnVe90W8AjYhUwVNI6Vez7YuATHZadDNwcEaOBm5N5gP2B0cnjOOD8Kl7PWoDvXlQbvWmc49w2awhpLuQyC7hd0tXAG+0LI+Kc7p4UEbdKGtlh8QRgz2R6MjAN+Hay/JLkw+MuSYMlDYuIuSniszLuA7c0ImKVpKGS1invB0/5XOe2WQNIU8BfTB59gN7ehnDTssR9Cdg0mR4OvFC23exk2TuSXNJxlFrybLnllr0Mx6ylzaKKxnkXnNtmdZbmSmynZfHCERGSKj4fGhEXABcAjBs3zudTzapXy8b5Gs5ts/pIcwReSy+3nz6TNIzS/cUB5gBblG03IllmthYPeqmdGjfOndtWMY9p6Z00XyOrpauBo5Lpo4C/li0/Mhmxuguw0H1kZoXi3Darsy4LuKQTe7NjSb8H7gTeI2m2pGOAHwH7SpoB7JPMQ+nrK88AM4FfA8f35rXNLDvObbPG0N0p9C8Dv6h2xxFxWBer3nETlGSE6gnVvpaZpSfpxIhwbpsVXL1PoZv1invMauLLeQdgBh7T0lvdHYF/QNKiTpaLUsN6w4xiMjMzsx50V8Afjogd6xaJmdWLG+dmTaDeXyMzs/y5cW7WBLrrA/9j3aKwmnGfkpkVhT+ueqe7Ar5n+4Sk72QfilnP0t1rw3rgxrlZE+iugA8tmz4k60CsNnwzE0thz/YJN87Niqu7Au5DHbPm5Ma5WRPobhDb1sldilQ2vUZEHJRpZGaWFTfOzZpAdwV8Qtn0T7IOxCwNV56acOPcGoLHtPROlwU8Im5pn5Y0NFk2vx5BmVmm3Dg3awJdFnBJAk4BTqLUVy5JK4GfR8TpdYrPzGrv2Yh4Pu8gzKx3uhvE9g1gD2B8RGwcERsBOwO7S/pGXaIzsyz8pX1C0p/yDMTMqtddAT8COCwinm1fEBHPAF8Ejsw6MLPOuMusJsq/bLh1blFYy3M69053g9j6R8QrHRdGxHxJ/TOMyaoRwR59HoYYnXck1viii2lrQJuxgIE6WZczAAALCElEQVRamncY1oC6K+DLq1xnORgzbwr/ts4PuXHeOsA38w7HGtsHk5uZCFiv7MYmvplJA7qr7aRk6qu5xmGNp7sC/sFu7ljUllE8VqVBb70IwMBlc3OOxBpdRPTNOwYz673uvkbmJC+kZr+Wqs/4WmuKCNRk10r2mJbe6W4Qm5mZmTUoF3AzM7MCcgE3MzMrIBdwKxT3mVmrasr//WZ8T3XkAm5mZlZALuBmZmYF5AJuZmZWQC7gTSJidd4h1MWqpuwINDOrnAt4k3hrZamAr9uvOf+kG7aVrjm08M0VOUdilo9mbLpGU76r+mmoT3tJn5D0pKSZkk7OO54iWbpiFQDq01xXamq30QbrAPDKEl+Gv4ic29VZvbp1Clz47FrFGqaAS+oL/BewP7AdcJik7fKNqvFFBC++vpQXFryZdyiZ2mbIBkAw5aEXWbzMR+FF4tyuzqrVwdUPvph3GHVQKtw3PPYyq1qowVIL3d3MpN52AmYm9xxH0h+ACcBj1e7wjvP/hd1e/n2NwmtMAjYHvpoceO8w85cw6Zd5hpSJ30DpFjozgR/lG0u9PDvx74za7kN5h1ELNc3tBfPmsNF/jaGPmvvDvi9wcPn86YPzCiUzg4FZ7bfG+mOekdTP4/3ey3u/eyfq0/vj54Y5AgeGAy+Uzc9Olq1F0nGSpkuaPn/+/G53uOHCJ2sboVkdvbX4lbxDqJWa5vbypUuavnhb83rfyidqtq9GOgJPJSIuAC4AGDduXLdZ/P6Tp9YlpkawYMlbfOqMy5nHYM4/Yifes9lABq3XnwHr9qNvHxXqLkYRwVsrV7No6QpeX7qCf8x4hWNu2qG08oR7Yei2+QZYJ+/NO4A6S5vbw7Z6D0xaWLe48vaDqx/i2jseYLv3vo8T93o3mw1qY9B6/Wnr15c+BRvzsnp1sGT5ShYtXcHLi5Zx1l/u5fLXJpZWttDftFZ/tUYq4HOALcrmRyTLLKW5bALAfmM2yzmS3pFEW/++tPXvy7s2bGPbTQfCTcnKPr7LbQE5t3th+guLmcsm/PQjW7PjlhvlHU6v9OkjNmzrz4Zt/Rmx0focsfsomJJ3VMXVSKfQ7wVGSxolaR3g88DVOcdUGO2HKwPbGqlNlgE10r+speTc7oVX33gLgM0HrZdzJLU3ZOD6eYdQaA3zaR8RKyWdCFxPafzGbyLi0ZzDKoxlydfImjHJ1+Ij8MJxbveOkhOug9brn3MktTd4QFvPG1mXGqaAA0TEtcC1ecdRRMMHr8e/77ctnx47Iu9QsiUX8CJyblfv4i+N5+bH5zFo/eYr4O/ZrPlG1tdTQxVwq54kTtxrdN5hZK+P/2WttWw9dABbDx2QdxiZkM+o9Yo7FK1YnPBmzaNA345pRC7gViwexGZmBriAW9H4CNzMDHABt6LxIDYzM8AF3IrGR+BmZoALuBWNj8DNzAAXcCsaH4GbmQEu4FYUGwwt/fQodDMzwBdysaI49iZ4/i5/b9Ss2Uy8FDZ5d95RFJILuBXDRiNLDzNrLtsdlHcEheXzkWZmZgXkAm5mZlZALuBmZmYF5AJuZmZWQC7gZmZmBeQCbmZmVkAu4GZmZgXkAm5mZlZAioi8Y6iapPnAc3V4qSHAK3V4nTQcS+daNZatImJonV6rbpzbuXMsnatXLKnyutAFvF4kTY+IcXnHAY6lK47FqtFIfyvH0jnH0jWfQjczMysgF3AzM7MCcgFP54K8AyjjWDrnWKwajfS3ciydcyxdcB+4mZlZAfkI3MzMrIBcwM3MzArIBbwTkjaWdKOkGcnPjbrZdkNJsyX9Iq9YJO0g6U5Jj0p6SNKhNY7hE5KelDRT0smdrF9X0uXJ+rsljazl61cYyzclPZb8Hm6WtFVesZRt91lJIalhvn7Sqpzb79i/c7uKWMq2yze3I8KPDg/gLODkZPpk4Mxutj0X+B3wi7xiAbYFRifTmwNzgcE1ev2+wNPA1sA6wIPAdh22OR74VTL9eeDyjH4XaWL5GLB+Mv2vecaSbDcQuBW4CxiX5f+tH6n+bs7tt/ft3K4ylmS73HPbR+CdmwBMTqYnAwd3tpGkDwGbAjfkGUtEPBURM5LpF4F5QK2uzrUTMDMinomI5cAfkpi6ivFKYG9JqtHrVxRLREyNiDeT2buAERnEkSqWxA+AM4FlGcVhlXFuv825XWUsidxz2wW8c5tGxNxk+iVKibwWSX2As4F/zzuWDnHtRKnV+HSNXn848ELZ/OxkWafbRMRKYCGwSY1ev9JYyh0DXJdBHKlikTQW2CIi/jejGKxyzu23OberjKVRcrtfni+eJ0k3AZt1sup75TMREZI6+67d8cC1ETG7tw3SGsTSvp9hwKXAURGxuldBFZykLwLjgI/m9Pp9gHOAo/N4/Vbm3G5uzu23tWwBj4h9ulon6WVJwyJibpI48zrZbFfgw5KOBwYA60haEhFdDnjIMBYkbQj8L/C9iLir0hi6MQfYomx+RLKss21mS+oHDAIW1DCGSmJB0j6UPiA/GhFvZRBHmlgGAu8HpiVFYDPgakkHRcT0jGIynNsVcG5XF0vj5HYeHe+N/gB+zNqDS87qYfujyW6gS4+xUDqtdjPw9Qxevx/wDDCKtwd0jOmwzQmsPdDliox+F2li2ZHSKcbRGf+P9BhLh+2n4UFsuT+c22vt27ldZSwdts8tt+v+gkV4UOrjuRmYAdwEbJwsHwdc2Mn2WSZ5j7EAXwRWAA+UPXaoYQwHAE8lyfO9ZNnpwEHJdBvwR2AmcA+wdYZ/m55iuQl4uez3cHVesXTY1gW8AR7O7XfE4NyuIpYO2+aW276UqpmZWQF5FLqZmVkBuYCbmZkVkAu4mZlZAbmAm5mZFZALuJmZWQG17IVcmp2kVcDDZYsOjohZOYVjZjXi3LZ2/hpZk0quHDWgm/X9onRtYzMrEOe2tfMp9BYi6WhJf5R0DcldliT9h6R7k3vsnla27feS++HeJOn3kv49WT6t/d63koZImpVM95X047J9fTVZvmfynCslPSHpsva7GUkaL+kOSQ9KukfSQEm3StqhLI7bJH2wXr8jsyJybrcmn0JvXutJeiCZfjYiPp1M7wp8ICJelbQfMJrS7fNE6Xq+HwHeoHTZxB0p/Y/cD9zXw+sdAyyMiPGS1gVul9R+K8YdgTHAi8DtwO6S7gEuBw6NiHuT6z0vBS6idPWrr0vaFmiLiAd79Zsway7ObQNcwJvZ0ojYoZPlN0bEq8n0fsnjn8n8AEpJPxC4KpJ770q6OsXr7Qd8QNLnkvlByb6WA/dExOxkXw8AIyndlnBuRNwLEBGLkvV/BP6vpP8AvgxcnPYNm7UI57YBLuCt6I2yaQE/jIj/Lt9A0te7ef5K3u56aeuwr5Mi4voO+9oTKL9r0Cq6+b+LiDcl3QhMACYCH+omFjN7m3O7xbgPvLVdD3xZ0gAAScMlvQu4FThY0nqSBgIHlj1nFm8n3uc67OtfJfVP9rWtpA26ee0ngWGSxifbD0xuVwhwIXAecG9EvNard2jWmpzbLcBH4C0sIm6Q9D7gzmTsyRLgixFxv6TLKd3x5zngH2VP+wlwhaQjKN1Jqd2FlE6f3Z8MZJkPHNzNay+XdCjwc0nrUeoj2wdYEhH3SVoE/LZGb9WspTi3W4O/RmY9kjSJUvL9pE6vtzmlW/S9NyJW1+M1zVqRc7vYfArdGoqkI4G7Kd2D1wlu1iSc27XnI3AzM7MC8hG4mZlZAbmAm5mZFZALuJmZWQG5gJuZmRWQC7iZmVkB/X8GzTB3Q8elJQAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0xabd44610>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "freq=np.fft.fftfreq(1024)\n",
    "\n",
    "plt.figure(figsize=(7, 4))\n",
    "plt.subplot(1,2,1)\n",
    "plt.plot(freq,out_r,label='real')\n",
    "plt.plot(freq,out_i,label='imag')\n",
    "plt.title(\"1024-DFT\")\n",
    "plt.xlabel(\"Frequency\")\n",
    "plt.ylabel(\"DFT real and imaginary data\")\n",
    "plt.legend()\n",
    "plt.tight_layout()\n",
    "plt.subplot(1,2,2)\n",
    "plt.plot(freq,golden_op.real,label='real')\n",
    "plt.plot(freq,golden_op.imag,label='imag')\n",
    "plt.title(\"1024-FFT -Numpy\")\n",
    "plt.xlabel(\"Frequency\")\n",
    "plt.ylabel(\"FFT real and imaginary data\")\n",
    "plt.legend()\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
